<?php

/* Pages.php
 *
 * (C) 2012, StaySimple CMS team.
 *
 * This file is part of StaySimple.
 * http://code.google.com/p/stay-simple-cms/
 *
 * StaySimple is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * StaySimple is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with StaySimple.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Page controller that handles all requests for managing pages. Most of the 
 * methods just delegate to the <em>PageManager</em> making this controller a 
 * front-end to that manager.
 * 
 * @see PageManager
 */
class Pages extends Administration {

    private $manager;

    public function __construct() {
        parent::__construct();
        $this->manager = new PageManager();

        $this->validateUser();
    }

    /**
     * Lists existing pages allowing users to choose what actions are to be taken 
     * in those pages.
     * 
     * @param array $params Unused parameter.
     */
    public function start($params = array()) {
        $filter = false;

        $this->manager->loadAll();

        if (isset($_POST['filter'])) {
            $filter = intval($_POST['filter']);
            $_SESSION['filter'] = $filter;
        } else if (isset($_SESSION['filter'])) {
            $filter = intval($_SESSION['filter']);
        }

        $filterOptions = array(
            array('0', $this->t('STAY_PAGE_FILTER_ALL')),
            array('1', $this->t('STAY_PAGE_FILTER_PUBLISHED')),
            array('2', $this->t('STAY_PAGE_FILTER_UNPUBLISHED')),
        );
        $pages = $this->manager->getTopPages();
        if ($filter) {
            if ($filter == 1) {
                $pages = $this->manager->getPublishedPages();
            } else if ($filter == 2) {
                $pages = $this->manager->getUnpublishedPages();
            }
        }

        $this->render('list.pages', array(
            'pages' => $pages,
            'filter' => $filter,
            'filterOptions' => $filterOptions,
            'active' => 'pages'
        ));
    }

    /**
     * Allows a user to edit or create a new page.
     * 
     * @param array $params The parameters array:
     *  [0] - the page's name.
     */
    public function edit($params = array()) {
        $page = new Page('');
        $revisions = null;
        $this->manager->loadAll();
        if (isset($params[0]) && $params[0] != '') {
            $query = $this->manager->getPage($params[0]);

            if ($query) {
                $page = $query;
                $revisions = BackupManager::getBackups($page->getName(), true);
            }
        }

        $parentPages = array(array('', ''));
        foreach ($this->manager->getTopPages($page) as $top) {
            $parentPages[] = array($top->getName(), $top->getName());
        }

        $pageTemplates = array();
        foreach ($this->manager->listPageTemplates() as $pt) {
            $pageTemplates[] = array($pt->getFile(), $pt->getTitle());
        }

        $translations = explode(',', Config::getInstance()->get('editing.languages'));

        $this->render('edit.page', array(
            'page' => $page,
            'translations' => $translations,
            'parentPages' => $parentPages,
            'pageTemplates' => $pageTemplates,
            'revisions' => $revisions,
            'active' => 'pages'
        ));
    }

    /**
     * Saves a page data while creating or editing a page.
     * 
     * @param array $params The parameters array:
     *  [0] - the page's name if this is an existing page.
     */
    public function save($params = array()) {
        if (isset($_POST['Page'])) {

            $error = false;
            if (isset($params[0])) {
                if ($_POST['name'] != '' && $params[0] !== $_POST['name']) {
                    if (!$this->manager->rename($params[0], PageManager::cleanSlug($_POST['name']))) {
                        $this->queueMessage(new Message($this->t('STAY_PAGE_RENAME_ERROR'), Message::$ERROR));
                        $error = true;
                    }
                }
            } else {
                $_POST['name'] = PageManager::cleanSlug(empty($_POST['name']) ? $_POST['title'] : $_POST['name']);
            }

            if (!$error) {
                $page = new Page('');

                $page->bind($_POST);
                if (!$this->manager->savePage($page)) {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_SAVE_ERROR'), Message::$ERROR));
                } else {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_SAVE_SUCCESS')));
                }
            }

            $this->redirect('pages/edit/' . $page->getName());
        }

        $this->redirect('pages');
    }

    /**
     * Delete a single page.
     * 
     * @param array $params The parameters array:
     *  [0] - the page's name.
     */
    public function delete($params = array()) {
        if (isset($params[0]) && $params[0] != '') {
            try {
                $result = $this->manager->deletePage($params[0]);
                if ($result === true) {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_SUCCESS')));
                } else {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR'), Message::$ERROR));
                }
            } catch (UnexistingPageException $upe) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR_NOPAGE'), Message::$ERROR));
            } catch (Removing404Exception $r4e) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR_404'), Message::$ERROR));
            } catch (RemovingHomeException $rhe) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR_HOME'), Message::$ERROR));
            }
        } else {
            $this->queueMessage(new Message($this->t('STAY_PAGE_INVALID'), Message::$ERROR));
        }

        $this->redirect('pages');
    }

    /**
     * Removes the selected pages.
     * 
     * @param array $params Unused parameter.
     */
    public function deleteSelected($params = array()) {
        if (isset($_POST['select'])) {
            $names = $_POST['select'];

            $deletedCount = 0;
            $max = count($names);
            foreach ($names as $name) {
                try {
                    $result = $this->manager->deletePage($name);

                    if ($result !== true) {
                        $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_SELECTED_ERROR', array($name)), Message::$ERROR));
                    } else {
                        $deletedCount++;
                    }
                } catch (UnexistingPageException $upe) {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR_NOPAGE'), Message::$ERROR));
                } catch (Removing404Exception $r4e) {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR_404'), Message::$ERROR));
                } catch (RemovingHomeException $rhe) {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ERROR_HOME'), Message::$ERROR));
                }
            }

            if ($deletedCount == 0) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ALL_ERROR'), Message::$ERROR));
            } else if ($max != $deletedCount) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_SOME_ERROR')));
            } else {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ALL_SUCCESS')));
            }
        }
        $this->redirect('pages');
    }

    /**
     * Restores a previously deleted page from a page backup.
     * 
     * @param array $params The parameters array:
     *  [0] - the name of the page to restore and used for redirecting the user.
     *  [1] - the backup to use as a unix timestamp.
     */
    public function restore($params = array()) {
        if (isset($params[1])) {
            if (!BackupManager::revertPageBackup($params[0], $params[1])) {
                $this->queueMessage(new Message($this->t('STAY_BACKUP_RESTORE_ERROR')), Message::$ERROR);
            } else {
                $this->queueMessage(new Message($this->t('STAY_BACKUP_RESTORE_SUCCESS')));
            }
        } else {
            $this->queueMessage(new Message($this->t('STAY_BACKUP_RESTORE_NO_FILE')), Message::$ERROR);
        }

        if (isset($params[0])) {
            $this->redirect('pages/edit/' . $params[0]);
        } else {
            $this->redirect('pages');
        }
    }

    /**
     * Provides HTML data to Fancybox so that the page backup feature works. 
     * The data is not rendered using StaySimpe CMS's code and is returned as 
     * an AJAX response.
     * 
     * @param array $params The parameters array:
     *  [0] - the page name used to identify the folder containing the backups to show.
     *  [1] - the backup name as an unix timestamp.
     */
    public function preview($params = array()) {
        if (isset($params[0]) && isset($params[1])) {
            $path = DATAROOT . '/backups/' . $params[0] . '/' . $params[1];
            if (is_file($path)) {
                $xml = new XMLFile($path);

                $base = StaySimpleCMS::app()->getURL() . (Config::getInstance()->get('site.hideindex') ? '/' : 'index.php/');
                $link = $base . Config::getInstance()->get('system.path') . '/pages/restore/' . $params[0] . '/' . $params[1];
                $title = $this->t('STAY_PAGE_PREVIEW_REVERT_LINK_TITLE');


                echo str_replace(array('{REVERTLINK}', '{PAGETEXT}', '{REVERTLINKTITLE}'), array($link, strval($xml->text), $title), file_get_contents(
                                THEMEROOT . '/' . Config::getInstance()->get('system.theme') . '/_pagepreview.php')
                );
            }
        }
    }

    /**
     * Shows the deleted pages, if any exist, allowing the user to restore a page
     * that has been deleted.
     * 
     * @param array $params The options array is not used.
     */
    public function deleted($params = array()) {
        $this->manager->loadAll();

        $deleted = $this->manager->getDeletedPages();

        $this->render('deleted.page', array(
            'pages' => $deleted,
            'active' => 'pages'
        ));
    }

    public function removeDeleted($params = array()) {
        if (!empty($params[0])) {
            if (!BackupManager::deleteBackup($params[0])) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_ERROR_REMOVING_DELETED'), Message::$ERROR));
            } else {
                $this->queueMessage(new Message($this->t('STAY_PAGE_SUCCESS_REMOVING_DELETED')));
            }
        } else {
            $this->queueMessage(new Message($this->t('STAY_PAGE_INVALID_DELETED'), Message::$ERROR));
        }

        $this->redirect('pages/deleted');
    }

    public function restoreDeleted($params = array()) {
        if (!empty($params[0]) && !empty($params[1])) {
            if (!BackupManager::revertPageBackup($params[0], $params[1])) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_RESTORE_DELETED_ERROR'), Message::$ERROR));
            } else {
                $this->queueMessage(new Message($this->t('STAY_PAGE_RESTORE_DELETED_SUCCESS')));
            }
        } else {
            $this->queueMessage(new Message($this->t('STAY_PAGE_RESTORE_DELETED_INVALID'), Message::$ERROR));
        }

        $this->redirect('pages/deleted');
    }

    /**
     * @param array $params The options array is not used.
     */
    public function deleteSelectedDeleted($params = array()) {
        if (isset($_POST['select'])) {
            $names = $_POST['select'];

            $deletedCount = 0;
            $max = count($names);
            foreach ($names as $name) {
                if (!BackupManager::deleteBackup($name)) {
                    $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_SELECTED_DELETED_ERROR', array($name)), Message::$ERROR));
                } else {
                    $deletedCount++;
                }
            }

            if ($deletedCount == 0) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ALL_DELETED_ERROR'), Message::$ERROR));
            } else if ($max != $deletedCount) {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_SOME_DELETED_ERROR')));
            } else {
                $this->queueMessage(new Message($this->t('STAY_PAGE_DELETE_ALL_DELETED_SUCCESS')));
            }
        }
        $this->redirect('pages/deleted');
    }

    public function translate() {
        $page = new Page('');
        $revisions = null;
        $this->manager->loadAll();
        if (isset($params[0]) && $params[0] != '') {
            $query = $this->manager->getPage($params[0]);

            if ($query) {
                $page = $query;
                $revisions = BackupManager::getBackups($page->getName(), true);
            }
        }

        $parentPages = array(array('', ''));
        foreach ($this->manager->getTopPages($page) as $top) {
            $parentPages[] = array($top->getName(), $top->getName());
        }

        $pageTemplates = array();
        foreach ($this->manager->listPageTemplates() as $pt) {
            $pageTemplates[] = array($pt->getFile(), $pt->getTitle());
        }

        $translations = explode(',', Config::getInstance()->get('editing.languages'));

        $this->render('translate.page', array(
            'page' => $page,
            'translations' => $translations,
            'parentPages' => $parentPages,
            'pageTemplates' => $pageTemplates,
            'revisions' => $revisions,
            'active' => 'pages'
        ));
    }

}